<?php
// +----------------------------------------------------------------------
// | najing [ 通用后台管理系统 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2020 http://www.najingquan.com All rights reserved.
// +----------------------------------------------------------------------
// | Author: cou
// +----------------------------------------------------------------------

namespace app\common\model;

use think\model\concern\SoftDelete;
use think\Validate;

class User extends Common
{
    use SoftDelete;
    protected $deleteTime = 'isdel';

    protected $autoWriteTimestamp = true;
    protected $updateTime = 'utime';


    const STATUS_NORMAL = 1;        //用户状态 正常
    const STATUS_DISABLE = 2;       //用户状态 停用

    const SEX_BOY = 1;
    const SEX_GIRL = 2;
    const SEX_OTHER = 3;

    protected $rule = [
        //'username' => 'length:6,20|alphaDash',
        'mobile'   => ['regex' => '^1[3|4|5|6|7|8|9][0-9]\d{4,8}$'],
        'sex'      => 'in:1,2,3',
        'nickname' => 'length:2,50',
        'password' => 'length:6,20',
        'p_mobile' => ['regex' => '^1[3|4|5|6|7|8|9][0-9]\d{4,8}$'],
    ];
    protected $msg = [
        //'username.length' => '用户名长度6~20位',
        //'username.alphaDash' => '用户名只能是字母、数字或下划线组成',
        'mobile'   => '请输入一个合法的手机号码',
        'sex'      => '请选择合法的性别',
        'nickname' => '昵称长度为2-50个字符',
        'password' => '密码长度6-20位',
        'p_mobile' => '邀请人栏请输入一个合法的手机号码',
    ];


    /**
     * 用户账户密码登陆
     * @author cou
     */
    public function toLogin($data, $loginType = 1, $platform = 1)
    {
        $result = array(
            'status' => false,
            'data'   => '',
            'msg'    => ''
        );

        if (!isset($data['mobile']) || !isset($data['password'])) {
            $result['msg'] = '请输入手机号码或者密码';
            return $result;
        }
        //校验验证码
        if (session('?login_fail_num')) {
            if (session('login_fail_num') >= config('shop.login_fail_num')) {
                if (!isset($data['captcha']) || $data['captcha'] == '') {
                    return error_code(10013);
                }
                if (!captcha_check($data['captcha'])) {
                    return error_code(10012);
                };
            }
        }

        $userInfo = $this->where(array('username' => $data['mobile']))->whereOr(array('mobile' => $data['mobile']))->find();
        if (!$userInfo) {
            $result['msg'] = '没有找到此账号';
            return $result;
        }


        //判断是否是用户名登陆
        $userInfo = $this->where(array('username|mobile' => $data['mobile'], 'password' => $this->enPassword($data['password'], $userInfo->ctime)))->find();
        if ($userInfo) {
            if ($userInfo['status'] == self::STATUS_NORMAL) {
                $result = $this->setSession($userInfo, $loginType, $platform);            //根据登陆类型，去存session，或者是返回user_token
                hook('loginAfter',$userInfo);//登录后事件
            } else {
                return error_code(11022);
            }

        } else {
            //写失败次数到session里
            if (session('?login_fail_num')) {
                session('login_fail_num', session('login_fail_num') + 1);
            } else {
                session('login_fail_num', 1);
            }
            $result['msg'] = '密码错误，请重试';
        }

        return $result;


    }

    /**
     * 设置用户登录信息或者更新用户登录信息
     * @author cou
     * @param $userInfo
     * @param $data
     * @param $loginType            登陆类型1是存session，主要是商户端的登陆和网页版本的登陆,2就是token
     * @param int $platform 1就是普通的登陆，主要是vue登陆，2就是微信小程序登陆，3是支付宝小程序，4是app，5是pc，写这个是为了保证h5端和小程序端可以同时保持登陆状态
     * @param int $type 1的话就是登录,2的话就是更新
     * @return array
     */
    public function setSession($userInfo, $loginType, $platform = 1, $type = 1)
    {
        $result = [
            'status' => false,
            'data'   => '',
            'msg'    => ''
        ];
        //判断账号状态
        if ($userInfo->status != self::STATUS_NORMAL) {
            $result['msg'] = '此账号已停用';
            return $result;
        }


        switch ($loginType) {
            case 1:
                session('user', $userInfo->toArray());
                $result['status'] = true;
                break;
            case 2:
                $userTokenModel = new UserToken();
                $result         = $userTokenModel->setToken($userInfo['id'], $platform);
                break;
        }

        if ($type == 1) {
            $userLogModel = new UserLog();        //添加登录日志
            $userLogModel->setLog($userInfo['id'],$userLogModel::USER_LOGIN);
        }
        return $result;
    }

    /**
     * 编辑用户信息
     * @author cou
     */
    public function editInfo($id, $sex = '', $birthday = '', $nickname = '', $avatar = '')
    {
        $result = [
            'status' => false,
            'data'   => '',
            'msg'    => ''
        ];
        $data   = [];

        if ($sex != '') {
            $data['sex'] = $sex;
        }
        if ($birthday != '') {
            $data['birthday'] = $birthday;
        }
        if ($nickname != '') {
            $data['nickname'] = htmlentities($nickname);
        }
        if ($avatar != '') {
            $data['avatar'] = $avatar;
        }
        $re = $this->save($data, ['id' => $id]);
        if ($re !== false) {
            $userLogModel = new UserLog();
            $userLogModel->setLog($id,$userLogModel::USER_EDIT);
            $result['status'] = true;
            $result['msg']    = '保存成功';
            return $result;
        } else {
            return error_code(10005);
        }
    }


    /**
     * 密码加密方法
     * @author cou
     */
    private function enPassword($password, $ctime)
    {

        return md5(md5($password) . $ctime);
    }

    /**
     * where 搜索条件
     * @author cou
     */
    protected function tableWhere($post)
    {
        $where = [];
        if (isset($post['sex']) && $post['sex'] != "") {
            $where[] = ['sex', '=', $post['sex']];
        }
        if (isset($post['id']) && $post['id'] != "") {
            $where[] = ['id', '=', $post['id']];
        }
        if (isset($post['username']) && $post['username'] != "") {
            $where[] = ['username', 'like', '%' . $post['username'] . '%'];
        }
        if (isset($post['mobile']) && $post['mobile'] != "") {
            $where[] = ['mobile', '=', $post['mobile']];
        }
        if (isset($post['birthday']) && $post['birthday'] != "") {
            $where[] = ['birthday', '=', $post['birthday']];
        }
        if (isset($post['nickname']) && $post['nickname'] != "") {
            $where[] = ['nickname', 'like', '%' . $post['nickname'] . '%'];
        }
        if (isset($post['status']) && $post['status'] != "") {
            $where[] = ['status', '=', $post['status']];
        }
        if (isset($post['pmobile']) && $post['pmobile'] != "") {
            if ($puser_id = get_user_id($post['pmobile'])) {
                $where[] = ['pid', '=', $puser_id];
            } else {
                $where[] = ['pid', '=', '99999999'];       //如果没有此用户，那么就赋值个数值，让他查不出数据
            }
        }

        $result['where'] = $where;
        $result['field'] = "*";
        $result['order'] = "id desc";
        return $result;
    }

    /**
     * 根据查询结果，格式化数据
     * @author cou
     */
    protected function tableFormat($list)
    {
        foreach ($list as $k => $v) {
            if ($v['sex']) {
                $list[$k]['sex'] = config('params.user')['sex'][$v['sex']];
            }
            if ($v['status']) {
                $list[$k]['status'] = config('params.user')['status'][$v['status']];
            }
            if ($v['pid']) {
                $list[$k]['pid_name'] = get_user_info($v['pid']);
            }
            if ($v['ctime']) {
                $list[$k]['ctime'] = getTime($v['ctime']);
            }
            if (isset($v['avatar']) && $v['avatar']) {
                $list[$k]['avatar'] = _sImage($v['avatar']);
            }
        }
        return $list;
    }

    /**
     * 返回layui的table所需要的格式
     * @author cou
     */
    public function tableData($post, $isPage = true)
    {
        if (isset($post['limit'])) {
            $limit = $post['limit'];
        } else {
            $limit = config('paginate.list_rows');
        }
        $tableWhere = $this->tableWhere($post);

        if ($isPage) {
            $list        = $this->with(['grade'])->field($tableWhere['field'])->where($tableWhere['where'])->order($tableWhere['order'])->paginate($limit);
            $data        = $this->tableFormat($list->getCollection());         //返回的数据格式化，并渲染成table所需要的最终的显示数据类型
            $re['count'] = $list->total();
        } else {
            $list = $this->field($tableWhere['field'])->where($tableWhere['where'])->order($tableWhere['order'])->select();
            if (!$list->isEmpty()) {
                $data = $this->tableFormat($list->toArray());
            }
            $re['count'] = count($list);
        }

        $re['code'] = 0;
        $re['msg']  = '';

        $re['data'] = $data;

        return $re;
    }

    /**
     * 更新头像
     * @author cou
     */
    public function changeAvatar($id, $image_url)
    {
        $data['avatar'] = $image_url;
        $where['id']    = $id;
        if ($this->save($data, $where)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 获取用户信息
     * @author cou
     */
    public function getUserInfo($user_id){
        $result = [
            'status' => false,
            'data' => [],
            'msg' => ''
        ];
        $userInfo = $this::with("grade")
            ->field('id,username,mobile,sex,birthday,avatar,nickname,balance,point,grade,status,pid,password,ctime')
            ->where(array('id' => $user_id))
            ->find();
        if ($userInfo !== false) {
            $userInfo['avatar'] = _sImage($userInfo['avatar']);
            $userGradeModel = new UserGrade();
            $gradeinfo = $userGradeModel->where(['id' => $userInfo['grade']])->find();
            if ($gradeinfo) {
                $userInfo['grade_name'] = $gradeinfo['name'];
            } else {
                $userInfo['grade_name'] = "";
            }
            //判断是否有密码，如果有就是true，没有就是false
            if($userInfo['password']){
                $userInfo['password'] = true;
            }else{
                $userInfo['password'] = false;
            }

            $result['data'] = $userInfo;
            $result['status'] = true;
        } else {
            $result['msg'] = '未找到此用户';
        }
        return $result;
    }

    /**
     * 忘记密码，找回密码
     * @author cou
     */
    public function forgetPassword($mobile,$code,$newPwd)
    {
        $result = [
            'status' => false,
            'msg' => '',
            'data' => ''
        ];

        if(empty($code)){
            return error_code(10013);
        }
        $smsModel = new Sms();
        if (!$smsModel->check($mobile, $code, 'veri')) {
            return error_code(10012);
        }
        $userInfo = $this->where(['mobile'=>$mobile])->find();
        if(!$userInfo){
            $result['msg'] = '没有此手机号码';
            return $result;
        }
        return $this->editPwd($userInfo['id'], $newPwd,$userInfo['ctime']);
    }

    /**
     * 修改用户密码，如果用户之前没有密码，那么就不校验原密码
     * @author cou
     */
    public function changePassword($user_id,$newPwd,$password = ""){
        $result = [
            'status' => false,
            'msg' => '',
            'data' => ''
        ];
        //修改密码验证原密码
        $user = $this->get($user_id);
        if(!$user){
            return error_code(10000);
        }

        if($user['password']){
            if(!$password){
                $result['msg'] = "请输入原密码";
                return $result;
            }
            if ($user['password'] !== $this->enPassword($password, $user['ctime'])) {
                $result['msg']    = '原密码不正确!';
                return $result;
            }
        }
        return $this->editPwd($user_id, $newPwd,$user['ctime']);
    }


    /**
     *  修改密码
     * @author cou
     * @param $user_id
     * @param $pwd
     * @return array
     */
    private function editPwd($user_id, $newPwd,$ctime)
    {
        $result = [
            'status' => true,
            'msg'    => '',
            'data'   => ''
        ];

        if ($newPwd == '' || strlen($newPwd) < 6 || strlen($newPwd) > 16) {
            return error_code(11009);
        }

        $res_pwd = $this->save([
            'password' => $this->enPassword($newPwd, $ctime)
        ], ['id' => $user_id]);

        if (!$res_pwd) {
            $result['status'] = false;
            $result['msg']    = '原密码和新密码一样!';
            return $result;
        }

        $result['msg'] = '密码修改成功!';
        return $result;
    }


    /**
     * 获取用户手机号
     * @author cou
     */
    public function getUserMobile($user_id)
    {
        $where[] = ['id', '=', $user_id];
        $result  = $this->field('mobile')->where($where)->find();
        return $result['mobile'] ? $result['mobile'] : '';
    }


    /**
     * 通过手机号获取用户ID
     * @author cou
     */
    public function getUserIdByMobile($mobile)
    {
        $where[] = ['mobile', '=', $mobile];
        $where[] = ['status', '=', self::STATUS_NORMAL];
        $result  = $this->field('id')->where($where)->find();
        return $result['id'] ? $result['id'] : false;
    }


    /**
     * 绑定上级
     * @author cou
     * @param $user_id
     * @param $superior_id
     * @return array
     * @throws \think\exception\DbException
     */
    public function setMyInvite($user_id, $superior_id)
    {
        $return = [
            'status' => false,
            'msg'    => '填写邀请码失败',
            'data'   => ''
        ];
        if ($user_id == $superior_id) {
            $return['msg'] = '自己不能邀请自己';
            return $return;
        }

        $userInfo = $this->get($user_id);
        if ($userInfo['pid'] && $userInfo['pid'] != 0) {
            $return['msg'] = '已有上级邀请，不能绑定其他的邀请';
            return $return;
        }

        $superior = $this->get($superior_id);
        if (!$superior) {
            $return['msg'] = '不存在这个邀请码';
            return $return;
        }

        $flag = $this->isInvited($user_id, $superior_id);
        if ($flag) {
            $return['msg'] = '不允许填写下级的邀请码';
            return $return;
        }

        $data['pid']    = $superior_id;
        $where[]        = ['id', '=', $user_id];
        $return['data'] = $this->save($data, $where);
        if ($return['data'] !== false) {
            $return['status'] = true;
            $return['msg']    = '填写邀请码成功';
        }

        return $return;
    }


    /**
     * 判断user_id是否是pid的父节点或者祖父节点,如果是，就返回true，如果不是就返回false
     * @author cou
     */
    public function isInvited($user_id, $pid)
    {
        $where[] = ['id', '=', $pid];
        $info    = $this->field('pid')->where($where)->find();
        if (!$info || $info['pid'] == 0) {
            return false;
        } else {
            if ($info['pid'] == $user_id) {
                return true;
            } else {
                return $this->isInvited($user_id, $info['pid']);
            }
        }

    }

    /**
     * 获取用户分享码
     * @author cou
     * @param $user_id
     * @return float|int|string
     */
    public function getShareCodeByUserId($user_id)
    {
        $code = ((int)$user_id + 1234) * 3;
        return $code;
    }


    /**
     * 获取用户ID
     * @author cou
     * @param $code
     * @return float|int
     */
    public function getUserIdByShareCode($code)
    {
        $user_id = ((int)$code / 3) - 1234;
        return $user_id;
    }


    /**
     * 修改邀请人
     * @author cou
     */
    public function editInvite($id, $mobile)
    {
        $return = [
            'status' => false,
            'msg'    => '操作失败',
            'data'   => ''
        ];

        $where[]    = ['mobile', '=', $mobile];
        $inviteInfo = $this->where($where)->find();
        if (!$inviteInfo) {
            $return['msg'] = '没有这个手机号注册的用户';
            return $return;
        }
        if ($id == $inviteInfo['id']) {
            $return['msg'] = '自己不能邀请自己';
            return $return;
        }

        $isInvited = $this->isInvited($id,$inviteInfo['id']);
        if ($isInvited) {
            $return['msg'] = '不能关联这个邀请人，因为他是你的下级或者下下级';
            return $return;
        }
        $return['status'] = true;
        $return['msg']    = '操作成功';
        $return['data']   = $inviteInfo['id'];
        return $return;
    }


    /**
     * 后台添加用户
     * @author cou
     */
    public function manageAdd($data)
    {
        $return = [
            'status' => false,
            'msg'    => '添加失败',
            'data'   => ''
        ];

        if (isset($data['mobile'])) {
            if ($data['mobile'] == '') {
                $return['msg'] = '手机号不能为空';
                return $return;
            }
            if (!isMobile($data['mobile'])) {
                $return['msg'] = '请输入正确的手机号';
                return $return;
            }
            $flag = $this->checkUserByMobile($data['mobile']);
            if ($flag) {
                $return['msg'] = '手机号已经存在，请更换手机号重新添加';
                return $return;
            }
        }
        if(isset($data['password'])){
            if ($data['password'] == '' || strlen($data['password']) < 6 || strlen($data['password']) > 16) {
                return error_code(11009);
            }
            //密码效验
            if ($data['password'] !== $data['repassword']) {
                $return['msg'] = '两次输入的密码不一致，请重新输入。';
                return $return;
            }
        }
        //默认用户等级
        if(!isset($data['grade'])){
            $userGradeModel = new UserGrade();
            $gradeInfo = $userGradeModel->where('is_def','1')->find();
            if($gradeInfo){
                $data['grade'] = $gradeInfo['id'];
            }else{
                $data['grade'] = 0;
            }
        }


        $time                = time();
        $newData['username'] = null;
        $newData['mobile']   = isset($data['mobile']) ? $data['mobile'] : "";
        $newData['password'] = isset($data['password']) ? $this->enPassword($data['password'], $time) : "";
        $newData['sex']      = isset($data['sex']) ? $data['sex'] : 3;
        $newData['birthday'] = $data['birthday'] ? $data['birthday'] : null;
        $newData['avatar']   = isset($data['avatar']) ? $data['avatar'] : '';
        $newData['nickname'] = $data['nickname'];
        $newData['balance']  = 0;
        $newData['point']    = 0;
        $newData['ctime']    = $time;
        $newData['utime']    = $time;
        $newData['status']   = isset($data['status']) ? $data['status'] : self::STATUS_NORMAL;
        $newData['pid']      = isset($data['pid']) ? $data['pid'] : 0;
        $newData['grade']    = $data['grade'];
        $result         = $this->save($newData);
        $return['data'] = $this->id;
        if ($result) {
            $newData['id'] = $this->id;
            hook('addUserAfter', $newData);//添加用户后钩子
            if (session('manage.id')) {
                $userLogModel = new UserLog();
                $userLogModel->setLog(session('manage.id'), $userLogModel::USER_REG);
            }
            $return['status'] = true;
            $return['msg']    = '添加成功';

        }

        return $return;
    }


    /**
     * 后台修改用户
     * @author cou
     * @param $data
     * @return array
     */
    public function manageEdit($data)
    {
        $return = [
            'status' => false,
            'msg'    => '修改失败',
            'data'   => ''
        ];

        //校验数据
        $validate = new Validate($this->rule, $this->msg);
        if (!$validate->check($data)) {
            $return['msg'] = $validate->getError();
            return $return;
        }
        if (isset($data['p_mobile']) && $data['p_mobile'] != '') {
            $p = $this->editInvite($data['id'], $data['p_mobile']);
            if ($p['status'] === false) {
                $return['msg'] = $p['msg'];
                return $return;
            } else {
                $data['pid'] = $p['data'];
            }
        }
        if ($data['p_mobile'] == '') {
            $data['pid'] = '';
        }
        //输入密码时修改密码
        if (isset($data['password']) && $data['password'] != '') {
            if (strlen($data['password']) < 6 || strlen($data['password']) > 20) {
                $return['msg'] = '密码长度为6-20位';
                return $return;
            }
            //密码效验
            if ($data['password'] !== $data['repassword']) {
                $return['msg'] = '两次输入的密码不一致，请重新输入。';
                return $return;
            }
            $userInfo            = $this->get($data['id']);
            $newData['password'] = $this->enPassword($data['password'], $userInfo['ctime']);
        }

        $where[]             = ['id', '=', $data['id']];
        $newData['nickname'] = $data['nickname'];
        $newData['sex']      = $data['sex'] ? $data['sex'] : 3;
        $newData['birthday'] = $data['birthday'] ? $data['birthday'] : null;
        $newData['avatar']   = $data['avatar'];
        $newData['status']   = $data['status'];
        $newData['pid']      = $data['pid'];
        $newData['grade']    = $data['grade'];
        $result              = $this->update($newData, $where);
        $return['data']      = $result;

        if ($result) {
            $return['status'] = true;
            $return['msg']    = '修改成功';
        }

        return $return;
    }

    /**
     * 根据用户手机号获取用户id
     * @author cou
     */
    public function checkUserByMobile($mobile)
    {
        $where[] = ['mobile', '=', $mobile];
        $where[] = ['status', '=', self::STATUS_NORMAL];
        $res     = $this->field('id')->where($where)->find();
        return $res;
    }

    /**
     * 添加用户
     * @author cou
     */
    public function doAdd($data = [])
    {
        $result = $this->insert($data);
        if ($result) {
            return $this->getLastInsID();
        }
        return $result;
    }

    /**
     * 用户跟用户等级的关联
     * @author cou
     */
    public function grade()
    {
        return $this->hasOne("UserGrade", 'id', 'grade')->bind(['grade_name' => 'name']);
    }


}
